package com.macrounion.atv.processor;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.google.common.io.Files;
import com.macrounion.base.service.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.macrounion.atv.service.dto.req.SettingsReqDto;
import com.macrounion.atv.service.entity.Settings;
import com.macrounion.atv.service.service.SettingsService;
import com.macrounion.base.processor.BaseProcessor;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class SettingsProcessor extends BaseProcessor<Settings, Settings, SettingsService, Settings> {

    public List<Map<String, String>> getValues(List<String> names) {
        return this.service.getValues(names);
    }

    @Transactional
    public int saveSettings(SettingsReqDto reqDto) {
        List<Settings> settings = new ArrayList<>();
        Field[] fields = reqDto.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            Settings setting = new Settings();
            try {
                setting.setId(UUID.randomUUID().toString());
                setting.setCreatedTime(new Date());
                setting.setName(field.getName());
                setting.setValues(field.get(reqDto) == null ? null : field.get(reqDto).toString());
                settings.add(setting);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return this.service.saveSettings(settings);
    }

    @Transactional
    @CacheEvict(value = "settings", allEntries = true)
    public int updateSettings(SettingsReqDto reqDto) {
        List<Map<String, String>> settingsMapList = new ArrayList<>();
        Field[] fields = reqDto.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            try {
                Map<String, String> settingsMap = new HashMap<>();
                settingsMap.put(field.getName(), field.get(reqDto) == null ? null : field.get(reqDto).toString());
                settingsMapList.add(settingsMap);
                System.out.println(settingsMap);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return this.service.updateSettings(settingsMapList);
    }

    public String uploadFile(HttpServletRequest request, MultipartFile file, String path) {
        return upload(request, file, path);
    }

    private String upload(HttpServletRequest request, MultipartFile file, String filePath) {
        filePath = getFilePath(request, filePath) + "/" + DateTime.now().toString("yyyyMMdd");
        File dir = new File(filePath);
        System.out.println(file.getOriginalFilename());
        File f = new File(filePath,
                DateTime.now().toString("yyyyMMddhhmmss") + "." + Files.getFileExtension(file.getOriginalFilename())
        );
        try {
            if (!dir.exists()) {
                dir.mkdirs();
            }

            BufferedOutputStream write = new BufferedOutputStream(new FileOutputStream(f));
            write.write(file.getBytes());
            write.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(401, e.getMessage());
        }
        String url = f.getPath().replaceAll("\\\\", "/");
        return request.getContextPath() + url;
    }

    private String getFilePath(HttpServletRequest request, String filePath) {
        String path = request.getParameter("filePath");
        return filePath + (StringUtils.isBlank(path) ? "" : path);
    }

    @Cacheable(value = "settings", key = "#name")
    public Settings findByName(String name) {
        return this.service.getByName(name);
    }
}